package com.dddframework.security.domain.auth.service;

import com.dddframework.core.context.SpringContext;
import com.dddframework.kit.lang.StrKit;
import com.dddframework.security.domain.contract.constants.CacheConstants;
import lombok.SneakyThrows;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * 用户服务
 *
 * @author Jensen
 */
public interface IUserDetailService extends UserDetailsService {

    /**
     * 根据用户名登录
     *
     * @param username
     * @return
     */
    UserDetails loadByUsername(String username);

    /**
     * 根据手机号登录
     *
     * @param phone
     * @return
     */
    UserDetails loadByPhone(String phone);

    /**
     * 根据OpenID登录
     *
     * @param type
     * @param openId
     * @return
     */
    UserDetails loadByOpenId(String type, String openId);

    /**
     * 用户密码登录
     *
     * @param username 用户名
     */
    @Override
    @SneakyThrows
    default UserDetails loadUserByUsername(String username) {
        CacheManager cacheManager = SpringContext.getBean(CacheManager.class);
        Cache cache = cacheManager.getCache(CacheConstants.USER_CACHE);
        UserDetails userDetails = loadByUsername(username);
        if (userDetails.isAccountNonLocked()) {
            cache.put(username, userDetails);
        }
        return userDetails;
    }

    /**
     * 手机验证码登录
     *
     * @return UserDetails
     */
    @SneakyThrows
    default UserDetails loadUserByPhone(String phone, String code, Boolean checkCode) {
        // 校验验证码
        if (checkCode) {
            String key = CacheConstants.VER_CODE_DEFAULT + ":" + phone;
            String verifyCode = SpringContext.getBean(StringRedisTemplate.class).opsForValue().get(key);
            String enableTestCode = SpringContext.getEnv().getProperty("test.code.enable");
            if (!(Boolean.getBoolean(enableTestCode) && StrKit.equals("8888", code))) {
                if (StrKit.hasBlank(verifyCode, code) || !code.equalsIgnoreCase(verifyCode)) {
                    throw new RuntimeException("验证码不正确，或验证码过期");
                }
            }
        }
        return loadByPhone(phone);
    }

}